//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.DataLayer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using Microsoft.Research.DataLayer.ServiceModel;

    /// <summary>
    /// Implementation of Contract for silverlight service.
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    //[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    [ServiceBehavior]
    public class TridentService : ITridentService
    {
        /// <summary>
        /// 
        /// </summary>
        private Connection registryConnection;

        /// <summary>
        /// Initializes the <see cref="TridentService"/> class.
        /// </summary>
        static TridentService()
        {
            SR_Connection.Init();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TridentService"/> class.
        /// </summary>
        public TridentService()
        {
            //ConnectionManager.AlternateProviderLocation = @"E:\src\msr\sd\trident\4\Trident\Research\DataLayer\Services\DataLayerBroker\bin";
            ConnectionManager.AlternateProviderLocation = System.Web.HttpRuntime.BinDirectory;

            ConnectionManager mgr = ConnectionManager.CreateForAgent(
                ConnectionManager.CancelBehavior.ThrowException,
                ConnectionManager.Agent.WebService);
            registryConnection = mgr.PickConnection(ConnectionManagerBase.ConnectionUI.NeverShowUI);
        }

        #region ITridentService Members

        /// <summary>
        /// Gets the user role.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        public UserRole GetUserRole(UserModel user)
        {
            return Helper.GetUserRole(user, this.registryConnection);
        }

        /// <summary>
        /// Loads the user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <returns></returns>
        public UserModel LoadUser(string userName)
        {
            return Helper.LoadUserByName(userName, this.registryConnection);
        }

        /// <summary>
        /// Gets the workflow categories.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        public List<LeftPaneModel> GetWorkflowCategories(UserModel user)
        {
            return Helper.GetWorkflowCategories(user, this.registryConnection);
        }

        /// <summary>
        /// Gets all users my workflows.
        /// </summary>
        /// <param name="currentUser">The current user.</param>
        /// <returns></returns>
        public List<LeftPaneModel> GetAllUsersMyWorkflows(UserModel currentUser)
        {
            return Helper.GetAllUsersMyWorkflows(currentUser, this.registryConnection);
        }

        /// <summary>
        /// Gets my workflows for user.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        public List<LeftPaneModel> GetMyWorkflowsForUser(UserModel user)
        {
            return Helper.GetMyWorkflowsForUser(user, this.registryConnection);
        }

        /// <summary>
        /// Gets all shared workflows for current user.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        public List<LeftPaneModel> GetAllSharedWorkflowsForCurrentUser(UserModel user)
        {
            return Helper.GetAllSharedWorkflowsForCurrentUser(user, this.registryConnection);
        }

        /// <summary>
        /// Gets the workflow by id.
        /// </summary>
        /// <param name="workflowId">The workflow id.</param>
        /// <returns></returns>
        public DetailedWorkflowModel GetWorkflowById(Guid workflowId)
        {
            DetailedWorkflowModel workflowModel = null;
            try
            {
                Activity workflow = Activity.Load(workflowId, registryConnection);
                if (workflow != null && workflow.IsDeleted)
                {
                    workflow = null;
                }

                if (workflow != null)
                {
                    workflowModel = new DetailedWorkflowModel(workflow);
                    if (workflowModel != null)
                    {
                        Machine.ISearch searchQuery = Machine.ISearch.Create();
                        searchQuery.Query = Machine.ISearch.AND(
                            Machine.ISearch.Availability(EnumFieldBase.Condition.Equals, ExecutorAvailabiltiy.Online),
                            Machine.ISearch.IsDeleted(BooleanField.Condition.Equals, false),
                            Machine.ISearch.Type(EnumFieldBase.Condition.NotEquals, MachineType.Virtual),
                            Machine.ISearch.IsInteractiveExecution(BooleanField.Condition.Equals, workflow.IsInteractive));

                        foreach (Machine node in Machine.Search(searchQuery, registryConnection))
                        {
                            workflowModel.Nodes.Add(new NodeModel(node));
                        }
                    }
                }
            }
            catch (SecurityException)
            {
            }
            catch (BackendStorageException)
            {
            }
            catch (Exception)
            {
            }

            return workflowModel;
        }

        /// <summary>
        /// Gets the workflow required params.
        /// </summary>
        /// <param name="workflow">The workflow.</param>
        /// <returns></returns>
        public List<ParameterDescriptionModel> GetWorkflowRequiredParams(WorkflowModel workflow)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the available nodes.
        /// </summary>
        /// <param name="isInteractive">if set to <c>true</c> [is interactive].</param>
        /// <returns></returns>
        public List<NodeModel> GetAvailableNodes(bool isInteractive)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Terminates the job.
        /// </summary>
        /// <param name="jobID">The job ID.</param>
        /// <param name="user">The user.</param>
        public void TerminateJob(Guid jobID, UserModel user)
        {
            Helper.TerminateJob(jobID, user, this.registryConnection);
        }

        /// <summary>
        /// Checks for activity.
        /// </summary>
        /// <param name="workflow">The workflow.</param>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        public bool CheckForActivity(WorkflowModel workflow, UserModel user)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the job details.
        /// </summary>
        /// <param name="jobID">The job ID.</param>
        /// <returns></returns>
        public JobDetails GetJobDetails(Guid jobID)
        {
            return Helper.GetJobDetails(jobID, this.registryConnection);
        }

        /// <summary>
        /// Executes the workflow.
        /// </summary>
        /// <param name="jobDetails">The job details.</param>
        /// <param name="scheduledUser">The scheduled user.</param>
        /// <returns></returns>
        public JobDetails ExecuteWorkflow(JobDescriptionModel jobDetails, UserModel scheduledUser)
        {
            return Helper.ExecuteWorkflow(jobDetails, scheduledUser, this.registryConnection);
        }

        /// <summary>
        /// Gets the outputs.
        /// </summary>
        /// <param name="jobID">The job ID.</param>
        /// <returns></returns>
        public List<DataProductModel> GetOutputs(Guid jobID)
        {
            return Helper.GetOutputs(jobID, this.registryConnection);
        }

        #endregion
    }
}
